#include <iostream>
#include <pthread.h>
#include <thread>
#include <unistd.h>
#include <vector>
#include <cstring>
#include <cstdio>
#include "mutex.hpp"

using namespace std;
//用多线程模拟一次抢票，总票数为1000

#define NUM 4

pthread_mutex_t lock = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;

class ThreadData{
public:
	ThreadData(int number/*,pthread_mutex_t* _lock*/){
		threadname = "thread-" + to_string(number);
		// lock = _lock;
	}

	string threadname;
	// pthread_mutex_t* lock;
};

int tickets = 1000;

// void* ticketget(void* args)
// {
// 	ThreadData* td = static_cast<ThreadData*>(args);
// 	while(true)
// 	{
// 		pthread_mutex_lock(&lock);  //用锁来保证任何时刻，这段代码只有一个执行流在执行，避免线程的并发导致的共享数据不准确
// 		// pthread_mutex_lock(&lock);  //死锁  ---- cpu和lock中相当于全是0，没有锁了，无法接着运行了
// 		if(tickets > 0){
// 			usleep(1000);
// 			printf("who = %s,get a ticket:%d\n",td->threadname.c_str(),tickets);
// 			tickets--;
// 			pthread_mutex_unlock(&lock);
// 		}
// 		else {
// 			pthread_mutex_unlock(&lock);  ///不等待会出现刚刚解锁，但是还没切换线程就又上锁的情况，导致实际上只有一个线程在抢票
// 			break;
// 		}
// 		usleep(15);
// 	}
// 	printf("%s quit sucess ....\n",td->threadname.c_str());

// 	return nullptr;
// }

void* ticketget(void* args)
{
	ThreadData* td = static_cast<ThreadData*>(args);
	while(true)
	{
		{
			LockGuard lockguard(&lock);
			if(tickets > 0){
				usleep(1000);
				printf("who = %s,get a ticket:%d\n",td->threadname.c_str(),tickets);
				tickets--;
			}
			else break;
		}
		usleep(15);
	}
	printf("%s quit sucess ....\n",td->threadname.c_str());

	return nullptr;
}

int main()
{	
	// pthread_mutex_t lock;  //栈
	// pthread_mutex_init(&lock,nullptr);

	vector<pthread_t> tids;
	vector<ThreadData*> tds;
	for(int i = 0;i < NUM;i++)
	{
		pthread_t tid;
		ThreadData* td = new ThreadData(i/*,&lock*/);
		pthread_create(&tid,nullptr,ticketget,td);
		tids.push_back(tid);
		tds.push_back(td);
	}
	for(auto tid : tids){
		pthread_join(tid,nullptr);
	}
	for(auto td : tds){
		delete td;
	}
	// printf("main exit\n");
	// pthread_exit(nullptr);
	return 0;
}

// #define NUM 3

// __thread int g_val = 100;
// // int g_val = 100;
// // int *p = NULL;

// string toHex(pthread_t tid)
// {
// 	char s[64];
// 	snprintf(s,sizeof(s),"%p",(void*)tid);
// 	return s;
// }

// class ThreadData{
// public:
// 	void Init(const string& name,int number)
// 	{
// 		threadname = name + to_string(number);
// 	}
// 	string threadname;
// };

// void* pthreadtoutine(void* args)
// {
// 	pthread_detach(pthread_self());
// 	int test_i = 0;
// 	ThreadData* td = static_cast<ThreadData*>(args);
// 	// if(td->threadname == "Thread-2") p = &test_i;
// 	int i = 0;
// 	while(i < 10){
// 		// cout << "pid : " << getpid() << " , tid : " << toHex(pthread_self()) << " , name: " << td->threadname 
// 		// << " , test_i : " << test_i << " , &test_i:" << &test_i << endl;
// 		// cout << "pid : " << getpid() << " , tid : " << toHex(pthread_self()) << " , name: " << td->threadname 
// 		// << " , g_val : " << g_val << " , &g_val:" << &g_val << endl;
// 		// test_i++,i++;
// 		g_val++,i++;
// 		sleep(1);
// 	}
// 	delete td;
// 	return nullptr;
// }

// int main()
// {
// 	vector<pthread_t> ph; 
// 	for(int i = 0;i < NUM;i++){
// 		ThreadData* td = new ThreadData;
// 		pthread_t tid;
// 		td->Init("Thread-",i);
// 		pthread_create(&tid,nullptr,pthreadtoutine,td);
// 		ph.push_back(tid);
// 		sleep(1);
// 	}
// 	// sleep(1);
// 	// cout << "p-val : " << *p << "  &val" << p << endl;
// 	// for(auto& tid : ph){
// 	// 	pthread_detach(tid);  //分离线程
// 	// }
// 	for(int i = 0;i < NUM;i++)
// 	{
// 		int n = pthread_join(ph[i],nullptr);
// 		printf("n = %d,error:%s\n",n,strerror(n));
// 	}
// 	sleep(10);
// 	return 0;
// }